// JoinInfo.cpp: implementation of the JoinInfo class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "phsshare.h"
#include "JoinInfo.h"
#include "FunctionStack.h"
#include "part.h"
#include "JointFunction.h"
#include "SupportHanger.h"
#include "PHSApp.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

JointInfo::JointInfo(ModelObject* pPart)
{
	m_pPart = pPart;
	m_nIndex = 1;
	m_pIterator = NULL;
}

JointInfo::~JointInfo()
{
	this->ClearIterator();
}

INT JointInfo::GetJointNum()
{
	INT nJointNum = 0;
	FunctionObject* pObject = NULL;
	FunctionStack* pStack = m_pPart->GetFunctionStack();
	ASSERT(pStack);
	FunctionStack::Iterator* pIterator = pStack->Get(FunctionObject::eJOINTFUNCTION);
	ASSERT(pIterator);

	for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
	{
		pObject = pIterator->Get();
		if(this->IsJointFunction(pObject))
		{
			nJointNum++;
		}
	}
	delete pIterator;

	return nJointNum;
}

JointFunction* JointInfo::GetFirst()
{
	FunctionStack* pStack = m_pPart->GetFunctionStack();
	ASSERT(pStack);

	FunctionObject* pObject = NULL;

	ClearIterator();

	m_pIterator = pStack->Get(FunctionObject::eJOINTFUNCTION);
	ASSERT_MEMORY_VALID(m_pIterator, NULL);

	for(m_pIterator->Begin(); !m_pIterator->End(); m_pIterator->Next())
	{
		pObject = m_pIterator->Get();
		return static_cast<JointFunction*>(pObject);
	}
	
	ClearIterator();

	return NULL;
}

JointFunction* JointInfo::GetNext()
{
	FunctionObject* pObject = NULL;
	ASSERT(m_pIterator);
	for(m_pIterator->Next(); !m_pIterator->End(); m_pIterator->Next())
	{
		pObject = m_pIterator->Get();
		return static_cast<JointFunction*>(pObject);
	}
	ClearIterator();
	return NULL;
}

BOOL JointInfo::IsJointFunction(FunctionObject *pFunction)
{
	ASSERT(pFunction);

	if(pFunction->IsKindOf(RUNTIME_CLASS_EX(JointFunction)))
		return TRUE;
	return FALSE;
}

void JointInfo::ClearIterator()
{
	if(m_pIterator != NULL)
	{
		delete m_pIterator;
		m_pIterator = NULL;
	}
}

INT JointInfo::GetUnJointNum()
{
	INT nJointNum = 0;
	FunctionObject* pObject = NULL;

	FunctionStackInterface* pStack = m_pPart->GetFunctionStack();
	ASSERT(pStack);

	FunctionStackInterface::Iterator* pIterator = pStack->Get(FunctionObject::eJOINTFUNCTION);

	for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
	{
		pObject = pIterator->Get();
		if(!static_cast<JointFunction*>(pObject)->HasJoint())
		{
			nJointNum++;
		}
	}
	delete pIterator;

	return nJointNum;
	
}

JointFunction* JointInfo::GetJointPort(const CString& strPortID)
{
	JointFunction* pFun = GetFirst();
	while(pFun != NULL)
	{
		if(strPortID == pFun->JointPortID())
			return pFun;
		pFun = GetNext();
	}
	return NULL;
}

JointFunction* JointInfo::GetJointPort(const AcGePoint3d& pt)
{
	JointFunction* pFun = GetFirst();
	while(pFun != NULL)
	{
		if((pt - GetPtInWCS(pFun)).length() <
			GetPHSApp()->PHSTolerance().EqualPoint())
		{
			return pFun;
		}
		pFun = GetNext();
	}
	return NULL;
}

AcGePoint3d JointInfo::GetPtInWCS(JointFunction* pFun)
{
	ASSERT(pFun);
	
	ASSERT(pFun->GetOwner()->IsKindOf(UE_RUNTIME_CLASS(Part)));

	Part* pPart = static_cast<Part*>(pFun->GetOwner());
	ASSERT(pPart);
	ASSERT(pPart->SupportHangerOwner());
	
	AcGePoint3d pt = pFun->PositionInOwner();
	pt.transformBy(pPart->ModelMatrix());
	pt.transformBy(pPart->SupportHangerOwner()->ModelMatrix());

	return pt;
}

FreeField JointInfo::GetFreeField(JointFunction* pFun)
{
	FreeField field;

	FreeField& Field = pFun->freeField();
	AcGeMatrix3d csFun = pFun->CoordinateInOwner();

	JointFunction* pTempFun = GetFirst();
	while(pTempFun != NULL)
	{
		if(pTempFun == pFun)
		{
			pTempFun = GetNext();
			continue;
		}
		AcGeMatrix3d csTemp = pTempFun->CoordinateInOwner();
		FreeField& tempField = pTempFun->freeField();

		AcGeMatrix3d csTran;
		AcGePoint3d pt;
		AcGeVector3d vX;
		AcGeVector3d vY;
		AcGeVector3d vZ;
		pt = GetCoordInTotherCS(csTemp, csFun, AcGePoint3d(0,0,0));
		vX = GetCoordInTotherCS(csTemp, csFun, AcGeVector3d(1,0,0));
		vY = GetCoordInTotherCS(csTemp, csFun, AcGeVector3d(0,1,0));
		vZ = GetCoordInTotherCS(csTemp, csFun, AcGeVector3d(0,0,1));

		if( !Field.IsXFree() ||
			(fabs(vX.x) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.x) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.x) > 0.0001 && !tempField.IsZFree()))
		{
			field.SetXUnFree();
		}
		
		if( !Field.IsYFree() ||
			(fabs(vX.y) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.y) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.y) > 0.0001 && !tempField.IsZFree()))
		{
			field.SetYUnFree();
		}
		
		if( !Field.IsZFree() ||
			(fabs(vX.z) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.z) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.z) > 0.0001 && !tempField.IsZFree()))
		{
			field.SetZUnFree();
		}
		
		if( !Field.IsvXFree() ||
			(fabs(vX.x) > 0.0001 && !tempField.IsvXFree()) ||
			(fabs(vY.x) > 0.0001 && !tempField.IsvYFree()) ||
			(fabs(vZ.x) > 0.0001 && !tempField.IsvZFree()) ||
			((fabs(pt.z) > 0.0001 || fabs(pt.y) > 0.0001) &&
			((fabs(vX.y) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.y) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.y) > 0.0001 && !tempField.IsZFree()) ||
			(fabs(vX.z) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.z) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.z) > 0.0001 && !tempField.IsZFree()))))
		{
			field.SetvXUnFree();
		}
		
		if( !Field.IsvYFree() ||
			(fabs(vX.y) > 0.0001 && !tempField.IsvXFree()) ||
			(fabs(vY.y) > 0.0001 && !tempField.IsvYFree()) ||
			(fabs(vZ.y) > 0.0001 && !tempField.IsvZFree()) ||
			((fabs(pt.x) > 0.0001 || fabs(pt.z) > 0.0001) &&
			((fabs(vX.x) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.x) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.x) > 0.0001 && !tempField.IsZFree()) ||
			(fabs(vX.z) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.z) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.z) > 0.0001 && !tempField.IsZFree()))))
		{
			field.SetvYUnFree();
		}
		
		if( !Field.IsvZFree() ||
			(fabs(vX.z) > 0.0001 && !tempField.IsvXFree()) ||
			(fabs(vY.z) > 0.0001 && !tempField.IsvYFree()) ||
			(fabs(vZ.z) > 0.0001 && !tempField.IsvZFree()) ||
			((fabs(pt.x) > 0.0001 || fabs(pt.y) > 0.0001) &&
			((fabs(vX.x) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.x) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.x) > 0.0001 && !tempField.IsZFree()) ||
			(fabs(vX.y) > 0.0001 && !tempField.IsXFree()) ||
			(fabs(vY.y) > 0.0001 && !tempField.IsYFree()) ||
			(fabs(vZ.y) > 0.0001 && !tempField.IsZFree()))))
		{
			field.SetvZUnFree();
		}
		
		pTempFun = GetNext();
	}
	return field;
}